home *** CD-ROM | disk | FTP | other *** search
/ Sounds Terrific 2 / Sounds Terrific II (1996)(Weird Science)(Disc 1 of 2)[Amiga-PC].iso / archives / amiga / tracker_4_31.lzh / tracker / lookup.c < prev    next >
C/C++ Source or Header  |  1995-02-21  |  6KB  |  257 lines

  1. /* lookup.c 
  2.     vi:ts=3 sw=3:
  3.  */
  4.  
  5. /* A simple database lookup.
  6.  * every entry in the database files is of the form: initial string value
  7.  * We just have to match the initial string, no separators required.
  8.  * Not that the specification just asks for a matching entry, not
  9.  * necessarily the first or the last.
  10.  */
  11. /* $Id: lookup.c,v 4.11 1995/02/21 17:54:32 espie Exp $ */
  12.  
  13. /* $Log: lookup.c,v $
  14.  * Revision 4.11  1995/02/21  17:54:32  espie
  15.  * Internal problem: buggy RCS. Fixed logs.
  16.  *
  17.  * Revision 4.10  1995/02/21  16:53:24  espie
  18.  * *** empty log message ***
  19.  *
  20.  * Revision 4.5  1995/02/01  16:39:04  espie
  21.  * Moved includes to defs.h
  22.  *
  23.  * Revision 1.2  1992/07/22  14:50:25  espie
  24.  * open_file changed, so lookup had to change to incorporate paths as well.
  25.  */
  26.  
  27. #include "defs.h"
  28. #include "extern.h"
  29.  
  30. ID("$Id: lookup.c,v 4.11 1995/02/21 17:54:32 espie Exp $")
  31.  
  32. /* the lookup structure is PRIVATE */
  33.  
  34. #define HANDLE 0    /* a null type, for memory handling */
  35. #define FNAME 1     /* a filename, which has not yet been opened */
  36. #define FOPENED 2   /* a file, once opened */
  37. #define STRING 3    /* an already accounted for string */
  38.  
  39. struct lookup
  40.    {
  41.    int type;
  42.    union 
  43.       {
  44.       char *filename;
  45.       FILE *file;
  46.       char *string;
  47.       char *path;
  48.       } value;
  49.    struct lookup *next;
  50.    };
  51.  
  52. /***
  53.  *
  54.  * lookup memory handling 
  55.  *
  56.  ***/
  57.  
  58. /* link_lookup(base, new): link a new element inside the existing chain */
  59. LOCAL void link_lookup(handle, new)
  60. struct lookup *handle, *new;
  61.    {
  62.    new->next = handle->next;
  63.    handle->next = new;
  64.    }
  65.  
  66. LOCAL void set_lookup(handle, path)
  67. struct lookup *handle;
  68. char *path;
  69.    {
  70.    handle->type = HANDLE;
  71.    handle->value.path = path;
  72.    }
  73.  
  74. /* new = create_lookup(): create an empty element, 
  75.  * chain anchor or to be filled 
  76.  */
  77. struct lookup *create_lookup(path)
  78. char *path;
  79.    {
  80.    struct lookup *new;
  81.  
  82.    new = (struct lookup *)malloc(sizeof(struct lookup));
  83.    if (!new)
  84.       exit(10);
  85.    set_lookup(path);
  86.    new->next = NULL;
  87.    return new;
  88.    }
  89.  
  90. /* free_lookup(handle): free the whole chain. Note that filenames
  91.  * do not belong to us
  92.  */
  93. void free_lookup(handle)
  94. struct lookup *handle;
  95.    {
  96.    struct lookup *to_free;
  97.  
  98.    while(handle)
  99.       {
  100.       to_free = handle;
  101.       handle = handle->next;
  102.       switch(to_free->type)
  103.          {
  104.       case HANDLE:
  105.       case FNAME: /* filenames don't belong to you */
  106.          break;
  107.       case FOPENED:
  108.          close_file(to_free->value.file.fhandle, 
  109.             to_free->value.file.filetype);
  110.          break;
  111.       case STRING:
  112.          free(to_free->value.string);
  113.          break;
  114.          }
  115.       free(to_free);
  116.       }
  117.    }
  118.  
  119. /* add_lookup(handle, filename): add a new potential filename to the lookup
  120.  * handle
  121.  */
  122. void add_lookup(handle, filename)
  123. struct lookup *handle;
  124. char *filename;
  125.    {
  126.    struct lookup *new;
  127.  
  128.    new = create_lookup();
  129.    new->type = FNAME;
  130.    new->value.filename = filename;
  131.    link_lookup(handle, new);
  132.    }
  133.  
  134.  
  135. /* postfix = check_prefix(template, s):
  136.  * if s is a prefix of template, return the remaining part of template,
  137.  * else return NULL.
  138.  * Note difference between NULL result and empty postfix (pointer to NULL)
  139.  */
  140. static char *check_prefix(template, s)
  141. char *template;
  142. char *s;
  143.    {
  144.    for (; *s; template++, s++)
  145.       /* *s != 0 at that point */
  146.       if (*template != *s)
  147.          return NULL;
  148.    while(*template == ' ' || *template == '\t')
  149.       template++;
  150.    return template;
  151.    }
  152.  
  153. /* copy = create_copy(s): allocate memory and create a copy of string s.
  154.  * get rid of spurious \n at the end.
  155.  */
  156. static char *create_copy(s)
  157. char *s;
  158.    {
  159.    char *new;
  160.    int len;
  161.  
  162.    len = strlen(s);
  163.    while(s[len - 1] == '\n')
  164.       s[--len] = 0;
  165.    new = malloc(len + 1);
  166.    if (!new)
  167.       exit(10);
  168.    return strcpy(new, s);
  169.    }
  170.  
  171. #define BUFSIZE 1500
  172.  
  173. LOCAL char *internal_lookup();
  174.  
  175. /* postfix = lookup(handle, s): lookup string s in the database indexed by
  176.  * handle.
  177.  */
  178. char *lookup(handle, s)
  179. struct lookup *handle;
  180. char *s;
  181.    {
  182.       /* the internal handler also maintains a current path */
  183.    return internal_lookup(handle, s, NULL);
  184.    }
  185.  
  186.  
  187. LOCAL char *internal_lookup(handle, s, path)
  188. struct lookup *handle;
  189. char *s;
  190. char *path;
  191.    {
  192.    char *r;
  193.    static char buffer[BUFSIZE];
  194.    struct lookup *new;
  195.  
  196.    if (handle)
  197.       {
  198.       switch(handle->type)
  199.          {
  200.       case STRING:
  201.          r = check_string(handle->value.string, s);
  202.          if (r)
  203.             return r;
  204.          else
  205.             return internal_lookup(handle->next, s, path);
  206.       case HANDLE:
  207.          return internal_lookup(handle->next, s,
  208.             handle->value.path ? handle->value.path : path);
  209.       case FNAME:
  210.          r = internal_lookup(handle->next, s, path);
  211.          if (r)
  212.             return r;
  213.          else
  214.             {
  215.             if (handle->value.file = 
  216.                open_file(handle->value.filename, "r", path))
  217.                {
  218.                handle->type = FOPENED;
  219.                return internal_lookup(handle, s, path);
  220.                }
  221.             else
  222.                {
  223.                set_lookup(handle, NULL);
  224.                return NULL;
  225.                }
  226.             }
  227.       case FOPENED:
  228.          r = internal_lookup(handle->next, s, path);
  229.          if (r)
  230.             return r;
  231.          else
  232.             {
  233.             if (fgets(buffer, BUFSIZE, handle->value.file))
  234.                {
  235.                new = create_lookup(NULL);
  236.                new->type = STRING;
  237.                new->value.string = create_copy(buffer);
  238.                link_lookup(handle, new);
  239.                r = check_prefix(new->value.string, s);
  240.                if (r)
  241.                   return r;
  242.                else
  243.                   return internal_lookup(handle, s, path);
  244.                }
  245.             else
  246.                {
  247.                close_file(handle->value.file);
  248.                set_lookup(new, NULL);
  249.                }
  250.             }
  251.          }
  252.       }
  253.    else
  254.       return NULL;
  255.    }
  256.             
  257.